package com.zycfc.zsf.boot.util.reflect;

import java.lang.annotation.*;
import java.lang.reflect.*;
import java.util.function.*;
import java.util.*;

public class ClassUtils
{
    public static final Set<Class<?>> basicClass;
    
    public static <T extends Annotation> T getAnnotation(final Class<?> clazz, final Class<T> annotation) {
        final T ann = clazz.getAnnotation(annotation);
        return (T)((ann != null) ? ann : ((clazz.getSuperclass() != Object.class) ? getAnnotation(clazz.getSuperclass(), (Class<Annotation>)annotation) : ann));
    }
    
    public static <T extends Annotation> T getAnnotation(final Method method, final Class<T> annotation) {
        final T ann = method.getAnnotation(annotation);
        if (ann != null) {
            return ann;
        }
        final Class<?> clazz = method.getDeclaringClass();
        final Class<?> superClass = clazz.getSuperclass();
        if (superClass != Object.class) {
            try {
                final Method suMethod = superClass.getMethod(method.getName(), method.getParameterTypes());
                return (T)getAnnotation(suMethod, (Class<Annotation>)annotation);
            }
            catch (NoSuchMethodException var6) {
                return null;
            }
        }
        return ann;
    }
    
    public static Class<?> getGenericTypeByType(final ParameterizedType genType, final int index) {
        final Type[] params = genType.getActualTypeArguments();
        if (index < params.length && index >= 0) {
            final Object res = params[index];
            return (Class<?>)((res instanceof Class) ? res : ((res instanceof ParameterizedType) ? ((Class)((ParameterizedType)res).getRawType()) : null));
        }
        return null;
    }
    
    public static Class<?> getGenericType(final Class<?> clazz, final int index) {
        final List<Type> arrys = new ArrayList<Type>();
        arrys.add(clazz.getGenericSuperclass());
        arrys.addAll(Arrays.asList(clazz.getGenericInterfaces()));
        return arrys.stream().filter(Objects::nonNull).map(type -> (clazz != Object.class && !(type instanceof ParameterizedType)) ? getGenericType(clazz.getSuperclass(), index) : getGenericTypeByType(type, index)).filter(Objects::nonNull).filter(res -> res != Object.class).findFirst().orElse(Object.class);
    }
    
    public static Class<?> getGenericType(final Class<?> clazz) {
        return getGenericType(clazz, 0);
    }
    
    public static boolean instanceOf(final Class<?> clazz, final Class<?> target) {
        if (clazz == null) {
            return false;
        }
        if (clazz == target) {
            return true;
        }
        if (target.isInterface()) {
            for (final Class<?> aClass : clazz.getInterfaces()) {
                if (aClass == target) {
                    return true;
                }
            }
        }
        if (clazz.getSuperclass() == target) {
            return true;
        }
        if (clazz.isInterface()) {
            for (final Class<?> aClass : clazz.getInterfaces()) {
                if (instanceOf(aClass, target)) {
                    return true;
                }
            }
        }
        return instanceOf(clazz.getSuperclass(), target);
    }
    
    public static boolean isBasicClass(final Class<?> clazz) {
        return ClassUtils.basicClass.contains(clazz);
    }
    
    static {
        (basicClass = new HashSet<Class<?>>()).add(Integer.TYPE);
        ClassUtils.basicClass.add(Double.TYPE);
        ClassUtils.basicClass.add(Float.TYPE);
        ClassUtils.basicClass.add(Byte.TYPE);
        ClassUtils.basicClass.add(Short.TYPE);
        ClassUtils.basicClass.add(Character.TYPE);
        ClassUtils.basicClass.add(String.class);
    }
}
